﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using Reborn_WorldServer.App1AppHandler;

namespace Reborn_Server.App1AppHandler
{
    public class AttackSequenceManager
    {
        public Creature MyCreature;

        public List<CreatureAttackWeapon> Attacks = new List<CreatureAttackWeapon>();
        public List<CreatureCastSpell> Spells = new List<CreatureCastSpell>();

        private ICreatureSequenceAction _CurrentAction;
        public ICreatureSequenceAction CurrentAction
        {
            get 
            {
                if (_CurrentAction == null)
                    ResetSequence();
                return _CurrentAction;
            }
            set 
            { 
                _CurrentAction = value; 
            }
        }

        private int CurrentSequence = 1;

        public AttackSequenceManager(Creature myCreature)
        {
            MyCreature = myCreature;
        }

        public int maxSequence
        {
            get
            {
                int maxSeq = 0;
                foreach (CreatureCastSpell ccs in Spells)
                {
                    if (ccs.Sequence > maxSeq)
                        maxSeq = ccs.Sequence;
                }
                foreach (CreatureAttackWeapon caw in Attacks)
                {
                    if (caw.Sequence > maxSeq)
                        maxSeq = caw.Sequence;
                }

                return maxSeq;
            }
        }

        public bool moveToValidSpellAttack()
        {
            List<CreatureCastSpell> validSpells = new List<CreatureCastSpell>();
            List<CreatureCastSpell> closestSequenceSpells = new List<CreatureCastSpell>();

            //Find the spells that we can cast
            foreach (CreatureCastSpell ccs in Spells)
            {
                if (ccs.Instant == false && (ccs.spellIcon.ManaCost <= MyCreature.Mana && MyCreature.buffManager.IsSilenced() == false) &&
                    !(ccs.spellIcon.CastType == "Self" && MyCreature.buffManager.GetBuffByStackType(ccs.spellIcon.StackType) != null))
                    validSpells.Add(ccs);
            }

            if (validSpells.Count > 0)
            {
                //Tells us how many sequences ahead the choosen action will be. Starts out high, gets lower
                //because the lower it is, the closer we our to our current sequence. Which is good.
                int movesAway = maxSequence + 1;
                int sequenceToMoveTo = CurrentSequence;
                foreach (CreatureCastSpell ccs in validSpells)
                {
                    //Counts how many sequences in the future this move is
                    int moveCounter = 0;
                    //We itterate this just like moveing through sequences, and the move counter counts how many times.
                    int sequenceCounter = CurrentSequence;
                    while (true)
                    {
                        //Stop when we find the correct sequence
                        if (ccs.Sequence == sequenceCounter)
                            break;

                        //Count how many sequences we've changed
                        moveCounter++;

                        //Move to the next sequence
                        sequenceCounter++;
                        //If the sequence is to high, go back to 1
                        if (sequenceCounter > maxSequence)
                            sequenceCounter = 1;
                    }
                    //If this action turned out to be closer than any we have already, wipe the list and start over
                    if (moveCounter < movesAway)
                    {
                        closestSequenceSpells = new List<CreatureCastSpell>();
                        closestSequenceSpells.Add(ccs);
                        movesAway = moveCounter;
                        sequenceToMoveTo = sequenceCounter;
                    }
                    //If this action is on the same sequence as the ones we have now, add it to the list
                    else if (movesAway == moveCounter)
                        closestSequenceSpells.Add(ccs);
                }

                int totalFrequencyRange = 0;
                foreach (CreatureCastSpell ccs in closestSequenceSpells)
                    totalFrequencyRange = totalFrequencyRange + ccs.Frequency;

                int rangeToUse = MyCreature.GameHandler.random.Next(1, totalFrequencyRange + 1);

                totalFrequencyRange = 0;
                foreach (CreatureCastSpell ccs in closestSequenceSpells)
                {
                    totalFrequencyRange = totalFrequencyRange + ccs.Frequency;
                    if (totalFrequencyRange >= rangeToUse)
                    {
                        CurrentAction = ccs;
                        CurrentSequence = sequenceToMoveTo;
                        return true;
                    }
                }
            }

            return false;
        }

        public void moveNextSequence()
        {
            int nextSequence = CurrentSequence + 1;
            if (nextSequence > maxSequence)
                nextSequence = 1;

            CurrentSequence = nextSequence;

            List<CreatureCastSpell> currentSequenceSpells = GetCurrentSequenceSpells();
            List<CreatureAttackWeapon> currentSequenceAttacks = GetCurrentSequenceAttacks();

            List<ICreatureSequenceAction> allSequenceActions = new List<ICreatureSequenceAction>();
            foreach (CreatureCastSpell ccs in currentSequenceSpells)
                allSequenceActions.Add((ICreatureSequenceAction)ccs);
            foreach (CreatureAttackWeapon caw in currentSequenceAttacks)
                allSequenceActions.Add((ICreatureSequenceAction)caw);

            int totalFrequencyRange = 0;
            foreach (ICreatureSequenceAction csa in allSequenceActions)
                totalFrequencyRange = totalFrequencyRange + csa.Frequency;

            int rangeToUse = MyCreature.GameHandler.random.Next(1, totalFrequencyRange + 1);

            totalFrequencyRange = 0;
            foreach (ICreatureSequenceAction csa2 in allSequenceActions)
            {
                totalFrequencyRange = totalFrequencyRange + csa2.Frequency;
                if (totalFrequencyRange >= rangeToUse)
                {
                    CurrentAction = csa2;
                    break;
                }
            }
        }

        public void ResetSequence()
        {
            CurrentSequence = 0;
            moveNextSequence();

            MyCreature.hateManager.ClearAllHateInfo();
        }

        //Returns all the attacks for the current sequence
        private List<CreatureAttackWeapon> GetCurrentSequenceAttacks()
        {
            List<CreatureAttackWeapon> CurrentSequenceAttacks = new List<CreatureAttackWeapon>();
            foreach (CreatureAttackWeapon weapon in Attacks)
            {
                if (weapon.Sequence == CurrentSequence)
                    CurrentSequenceAttacks.Add(weapon);
            }
            return CurrentSequenceAttacks;
        }

        //Returns all spells for the current sequence & available mana
        private List<CreatureCastSpell> GetCurrentSequenceSpells()
        {
            List<CreatureCastSpell> CurrentSequenceSpells = new List<CreatureCastSpell>();
            foreach (CreatureCastSpell spell in Spells)
            {
                if (spell.Sequence == CurrentSequence)
                    CurrentSequenceSpells.Add(spell);
            }

            return CurrentSequenceSpells;
        }
    }
}
